import * as crypto from 'crypto';
import { KSpaceConfig } from '../types';

/**
 * 生成OSS上传所需的签名
 * @param config 配置信息
 * @param method HTTP方法
 * @param resource 资源路径
 * @param headers 请求头
 * @returns 生成的签名
 */
export function generateSignature(
  config: KSpaceConfig,
  method: string,
  resource: string,
  headers: Record<string, string>
): string {
  // 构建规范化的头信息
  const canonicalizedOSSHeaders: string[] = [];
  const canonicalizedResource = `/${config.bucket}${resource}`;
  
  // 收集OSS相关的头信息
  Object.keys(headers).forEach(key => {
    if (key.toLowerCase().startsWith('x-oss-')) {
      canonicalizedOSSHeaders.push(`${key.toLowerCase()}:${headers[key]}`);
    }
  });
  
  canonicalizedOSSHeaders.sort();
  const canonicalizedOSSHeadersStr = canonicalizedOSSHeaders.join('\n');
  
  // 构建签名字符串
  const stringToSign = `${method}\n\n\n\n${canonicalizedOSSHeadersStr}\n${canonicalizedResource}`;
  
  // 使用HMAC-SHA1算法生成签名
  const hmac = crypto.createHmac('sha1', config.accessKeySecret);
  hmac.update(stringToSign);
  const signature = hmac.digest('base64');
  
  return `OSS ${config.accessKeyId}:${signature}`;
}

/**
 * 生成随机字符串
 * @param length 字符串长度
 * @returns 随机字符串
 */
export function generateRandomString(length: number): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
}

/**
 * 计算文件MD5值
 * @param file 文件对象或Buffer
 * @returns Promise<string> MD5值
 */
export function calculateFileMD5(file: File | Buffer): Promise<string> {
  return new Promise((resolve, reject) => {
    if (Buffer.isBuffer(file)) {
      const hash = crypto.createHash('md5');
      hash.update(file);
      resolve(hash.digest('base64'));
    } else if (typeof File !== 'undefined' && file instanceof File) {
      const reader = new FileReader();
      reader.onload = (e) => {
        if (e.target?.result) {
          const hash = crypto.createHash('md5');
          hash.update(Buffer.from(e.target.result as ArrayBuffer));
          resolve(hash.digest('base64'));
        } else {
          reject(new Error('Failed to read file'));
        }
      };
      reader.onerror = () => reject(new Error('Error reading file'));
      reader.readAsArrayBuffer(file);
    } else {
      reject(new Error('Unsupported file type'));
    }
  });
}